package com.studiofortress.sf.graphics;

import javax.media.opengl.GLAutoDrawable;
import java.awt.Dimension;

import javax.media.opengl.GL;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLEventListener;

/**
 * The Canvas is a specialist GLCanvas with some added setup code. This sets up
 * the size of the Canvas, disables resizing and adds some GL setup code.
 *
 * If you are looking for a class to create and draw too then it's advised to
 * use the GraphicsWindow, GraphicsFullScreen, GraphicsBorderlessWindow and
 * GraphicsPanel instead of this one.
 * 
 * When this is initialized the initializeGL method is called to setup the GL
 * pipeline with it's default settings. If you have your own specific settings
 * you want then override that method and place them there.
 *
 * @author Joseph Lenton
 * @version 26/12/2008
 */
public class GraphicsCanvas extends GLCanvas
{
    // this is the canvas that all other canvases will share their textures and
    // display lists. I do it by canvas because the canvases offer the GL pipelines
    // to the functions where the loading occures
    private static final GLContext SHARE_CONTEXT = new GLCanvas().getContext();

    /**
     * Makes a new GraphicsCanvas with the given width and height.
     * @param width The width for this GraphicsCanvas.
     * @param height The height for this GraphicsCanvas.
     */
    public GraphicsCanvas(int width, int height)
    {
        super(null, null, SHARE_CONTEXT, null);

        addGLEventListener(new GLEventListener()
        {
            private void initializeQueues(GL gl)
            {
                GLTexture.getTextureManager().initializeTextures();
                GLDisplayList.uninitializeDisplayLists(gl);
            }
            
            @Override
            public void init(GLAutoDrawable drawable)
            {
                final GL gl = drawable.getGL();
                initializeGL( gl );
                initializeQueues( gl );
            }
            
            @Override
            public void display(GLAutoDrawable drawable)
            {
                initializeQueues( drawable.getGL() );
            }

            @Override
            public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
            {
                GL gl = drawable.getGL();
                gl.glViewport(0, 0, width, height);
                gl.glMatrixMode(GL.GL_PROJECTION);
                gl.glLoadIdentity();
                gl.glOrtho(0, width, 0, height, -1, 1);

                gl.glMatrixMode(GL.GL_MODELVIEW);
                gl.glLoadIdentity();
                gl.glFlush();
            }

            @Override
            public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { }
        });
        
        setAutoSwapBufferMode(false);
        setIgnoreRepaint(true);
        Dimension size = new Dimension(width, height);
        setSize(size);
        setMinimumSize(size);
        setMaximumSize(size);
        setPreferredSize(size);
    }

    /**
     * Sets up and initializes the GL pipeline for this canvas with the default
     * settings. Override this to set your own custom settings instead.
     * @param gl The GL pipeline for this GraphicsCanvas
     */
    protected void initializeGL(GL gl)
    {
        // Enable VSync
//      gl.setSwapInterval(1);

        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // black
        gl.glEnable(GL.GL_BLEND);
        gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
        gl.glShadeModel(GL.GL_FLAT);
    }
}
